import { merge } from 'lodash'

export type ApiKey =
  | 'paginate_entity_plus'
  | 'overview'
  | 'add_column'
  | 'aggregate_avg'
  | 'aggregate_count'
  | 'aggregate_max'
  | 'aggregate_min'
  | 'aggregate_sum'
  | 'column_exists'
  | 'create_table'
  | 'delete_entity'
  | 'delete_record'
  | 'drop_column'
  | 'drop_table'
  | 'execute_raw_sql'
  | 'get_column_types'
  | 'get_primary_key'
  | 'get_table_columns'
  | 'get_tables'
  | 'get_uuid'
  | 'insert_record'
  | 'paginate_entity'
  | 'rename_column'
  | 'rename_table'
  | 'save_entity'
  | 'select_one_record'
  | 'select_join'
  | 'select_records'
  | 'table_exists'
  | 'truncate_table'
  | 'update_entity'
  | 'update_record'
  | 'fixed_table'
  | 'get_tables_used'
  | 'set_tables_used'

export interface ApiResponse<T = any> {
  message: string
  code: number
  result?: T
}

export interface ApiError {
  message: string
  code: number
}

export interface RequestOption<P> {
  key: ApiKey
  params?: P
  immediate?: boolean
  watching?: boolean
}

export interface RequestReactive<P, T> {
  data: T | null
  error: ApiError | null,
  loading: boolean
  refresh: (params?: P) => void
}

export const useRequest = <P, T = any>(option: RequestOption<P>): RequestReactive<P, T> => {
  const result = reactive<RequestReactive<P, T>>({
    data: null,
    error: null,
    loading: false,
    refresh: () => {}
  })

  const url = `/api/${option.key}`

  console.log(option, url)

  const makeRequest = (params?: P): void => {
    result.loading = true
    $fetch<ApiResponse<T>>(url, {
      method: 'POST',
      body: params || option.params || {},
    })
      .then((response) => {
        result.data = response.result as any
        result.error = null
      })
      .catch((err: any) => {
        result.error = {
          message: err.message || 'unknown error',
          code: err.statusCode || 500
        }
        result.data = null
      })
      .finally(() => {
        result.loading = false
      })
  }

  result.refresh = (args?: P) => {
    const params = merge({}, option.params, args || {})
    makeRequest(params)
  }

  if (option.immediate) {
    makeRequest(option.params)
  }

  return result as RequestReactive<P, T>
}